/**
 * Copyright 2006 gworks.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 */
package org.javaongems.client.service;

import org.javaongems.client.Gem;

import com.google.gwt.user.client.rpc.IsSerializable;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.SerializableException;

/**
 * <p>Provides the specification to collect and operate on data that was posted  
 * 	via the HttpPostForm or similar style widget</p>
 * <p>Responsibilties:
 * <ul>
 * 	<li> pickup and handle posted data
 * </ul>	 
 * </p>
 * <p>Collaborators:
 * <ul>
 * 	<li> Http post form
 * </ul>
 * </p>
 * @author Ashin Wimalajeewa (ash)
 */
public interface HttpPostRpc extends RemoteService {
	/**
	 * Delimiter used to separate the Gem id and the Gem order no. 
	 */
	public String GEM_DELIM = "-.-";
	public char REQUEST_DELIM = '/';
	
	public int GEM_DELIM_LEN = GEM_DELIM.length();
	
	/**
	 * Note, you will need to append a "*" character in the web.xml file 
	 * entry in order for it to process each and every match.
	 */
	public String POST_CTX = "/gems.io.httppost.action.keeper" + REQUEST_DELIM;
	public String DEFAULT_SERVICE_CTX = "/gems.io.httppost.pickup";
	
	/**
	 * Picks up and handles the posted order/package uniquely identified by
	 * the gemId and the orderNo.
	 * <p>Constraint:
	 * <ul>
	 * 	<li> Do not attempt to asynchronously run both pingProgress and 
	 * 		pickupAndHandle. Such seem to cause the browser to enter into
	 * 		a deadlock state.
	 * </ul>
	 * </p> 
	 * <p>Notes:
	 * <ul>
	 * 	<li> It is not required to ping progress prior to calling pickup and
	 * 		handle.
	 * </ul>
	 * </p> 
	 * 
	 * @param gemId - the gem id generated by the server
	 * @param orderNo - the order no generated by the Http post form widget
	 * @throws SerializableException - if known application specific exception 
	 * 	was thrown on the server (as opposed to IOException/ServletException)
	 */
	public void pickupAndHandle(String gemId, String orderNo) throws SerializableException;
	
	/**
	 * Return the current progress of the http posted order/package that has 
	 * been dispatched and scheduled for pickup.
	 * <p>Constraint:
	 * <ul>
	 * 	<li> Do not attempt to asynchronously run both pingProgress and 
	 * 		pickupAndHandle. Such seem to cause the browser to enter into
	 * 		a deadlock state.
	 * </ul>
	 * </p> 
	 * 
	 * @param gemId - the gem id generated by the server
	 * @param orderNo - the order no generated by the Http post form widget
	 * @return - a valid progress object or null if the dispatch and pickup
	 * has either failed or completed
	 */
	public ProgressInfo pingProgress(String gemId, String orderNo);
	
	static public class ProgressInfo implements IsSerializable {
		static public int FAILED_PHASE = -1;
		static public int DISPATCHING_PHASE = 0;
		static public int UPLOADING_PHASE = 1;
		static public int PROCESSING_PHASE = 2;
		
		public int currentPhase = DISPATCHING_PHASE;
		public int phaseCount = 2;
		public String phaseName = "transit";
		public float phasePercentageComplete = 0f;
		public String statusMessage = "dispatching payload";
		
		// byte info
		public long bytesRead;
		public long totalBytes;
		
		public String toString() {
			StringBuffer ret = new StringBuffer();
			ret.append("phase:").append(currentPhase).append("/").append(phaseCount);
			ret.append("[").append(phaseName).append("] ").append(phasePercentageComplete);
			ret.append("% - ").append(statusMessage);
			return ret.toString();
		}
	}
	
	static public class Utils {
		/**
		 * Prepares an endpoint for use with the HttpPostForm widget's 
		 * setAction(). Hence, this method will be called from the client.
		 * @param orderNo - order no associated with this post
		 * @return a prepared string that is targetted at the http post keeper action
		 * @see #parseGemIdAndOrderNo(String)
		 */
		static public String prepareEndpoint(String orderNo) {
			String epRootCtx = Gem.stone.getEndpointForService(HttpPostRpc.POST_CTX);
			StringBuffer ret = new StringBuffer(epRootCtx);
			String gemId = Gem.stone.getGemId();
			ret.append(gemId);
			ret.append(GEM_DELIM);
			ret.append(orderNo);
			return ret.toString();
		}
		
		/**
		 * Parses the gem Id and order no from the path info that was part of 
		 * the http servlet request. Hence, this method will be called from the
		 * server-side.
		 * @param pathInfo
		 * @return
		 */
		static public String[] parseGemIdAndOrderNo(String pathInfo) {
			String[] ret = new String[2];
			int delimPos = pathInfo.indexOf(GEM_DELIM);
			int reqPos = pathInfo.lastIndexOf(REQUEST_DELIM, delimPos);
			ret[0] = pathInfo.substring(reqPos+1, delimPos);
			ret[1] = pathInfo.substring(delimPos + GEM_DELIM_LEN);
			return ret;
		}
	}
}
